home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / communication / bbs / termv4.6 / extras / source / term-source.lha / Translate.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-18  |  22.0 KB  |  1,123 lines

  1. /*
  2. **    Translate.c
  3. **
  4. **    Character translation support routines
  5. **
  6. **    Copyright © 1990-1996 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #ifndef _GLOBAL_H
  11. #include "Global.h"
  12. #endif
  13.  
  14.     /* Translation chunk header types. */
  15.  
  16. enum    {    TYPE_NONE, TYPE_SEND, TYPE_RECEIVE };
  17.  
  18.     /* Master translation table entry types. */
  19.  
  20. enum    {    TRANSLATION_VERBATIM, TRANSLATION_IGNORE, TRANSLATION_OTHER };
  21.  
  22.     /* Symbolic names for character codes. */
  23.  
  24. STATIC struct { STRPTR Name; UBYTE Value; } CodeTab[44] =
  25. {
  26.     {    "NUL",    0    },
  27.     {    "SOH",    1    },
  28.     {    "STX",    2    },
  29.     {    "ETX",    3    },
  30.     {    "EOT",    4    },
  31.     {    "ENQ",    5    },
  32.     {    "ACK",    6    },
  33.     {    "BEL",    7    },
  34.     {    "BS",    8    },
  35.     {    "HT",    9    },
  36.     {    "LF",    10    },
  37.     {    "VT",    11    },
  38.     {    "FF",    12    },
  39.     {    "CR",    13    },
  40.     {    "SO",    14    },
  41.     {    "SI",    15    },
  42.     {    "DLE",    16    },
  43.     {    "DC1",    17    },
  44.     {    "DC2",    18    },
  45.     {    "DC3",    19    },
  46.     {    "DC4",    20    },
  47.     {    "NAK",    21    },
  48.     {    "SYN",    22    },
  49.     {    "ETB",    23    },
  50.     {    "CAN",    24    },
  51.     {    "EM",    25    },
  52.     {    "SUB",    26    },
  53.     {    "ESC",    27    },
  54.     {    "FS",    28    },
  55.     {    "GS",    29    },
  56.     {    "RS",    30    },
  57.     {    "US",    31    },
  58.     {    "SP",    32    },
  59.     {    "DEL",    127    },
  60.     {    "SS2",    142    },
  61.     {    "SS3",    143    },
  62.     {    "DCS",    144    },
  63.     {    "CSI",    155    },
  64.     {    "ST",    156    },
  65.     {    "OSC",    157    },
  66.     {    "PM",    158    },
  67.     {    "APC",    159    },
  68.     {    "NBS",    160    },
  69.     {    "SHY",    173    }
  70. };
  71.  
  72.     /* TranslateSetup():
  73.      *
  74.      *    Set up for buffer translation.
  75.      */
  76.  
  77. VOID
  78. TranslateSetup(struct TranslationHandle *Handle,STRPTR SourceBuffer,LONG SourceLen,STRPTR DestinationBuffer,LONG DestinationLen,struct TranslationEntry **Table)
  79. {
  80.     Handle -> LocalBuffer        = NULL;
  81.     Handle -> LocalLen        = 0;
  82.  
  83.     Handle -> SourceBuffer        = SourceBuffer;
  84.     Handle -> SourceLen        = SourceLen;
  85.  
  86.     Handle -> DestinationBuffer    = DestinationBuffer;
  87.     Handle -> DestinationLen    = DestinationLen;
  88.  
  89.     Handle -> Table            = Table;
  90. }
  91.  
  92.     /* TranslateBuffer(struct TranslationHandle *Handle):
  93.      *
  94.      *    Translate buffer contents according to
  95.      *    translation table contents.
  96.      */
  97.  
  98. LONG
  99. TranslateBuffer(struct TranslationHandle *Handle)
  100. {
  101.     register STRPTR                 Data        = Handle -> DestinationBuffer;
  102.     register LONG                 BytesWritten    = 0;
  103.     register struct TranslationEntry    *Entry;
  104.  
  105.         /* Are we to return any translated data? */
  106.  
  107.     while(Handle -> LocalLen && BytesWritten < Handle -> DestinationLen)
  108.     {
  109.             /* Decrement number of bytes in buffer. */
  110.  
  111.         Handle -> LocalLen--;
  112.  
  113.             /* Return next character. */
  114.  
  115.         *Data++ = *Handle -> LocalBuffer++;
  116.  
  117.             /* Add another byte. */
  118.  
  119.         BytesWritten++;
  120.     }
  121.  
  122.         /* Loop until done. */
  123.  
  124.     while(Handle -> SourceLen && BytesWritten < Handle -> DestinationLen)
  125.     {
  126.             /* Another byte eaten. */
  127.  
  128.         Handle -> SourceLen--;
  129.  
  130.             /* Get table entry. */
  131.  
  132.         if(Entry = Handle -> Table[*Handle -> SourceBuffer++])
  133.         {
  134.                 /* Copy to local data area. */
  135.  
  136.             Handle -> LocalBuffer    = Entry -> String;
  137.             Handle -> LocalLen    = Entry -> Len;
  138.  
  139.                 /* Translate the data. */
  140.  
  141.             while(Handle -> LocalLen && BytesWritten < Handle -> DestinationLen)
  142.             {
  143.                     /* Decrement number of bytes in buffer. */
  144.  
  145.                 Handle -> LocalLen--;
  146.  
  147.                     /* Return next character. */
  148.  
  149.                 *Data++ = *Handle -> LocalBuffer++;
  150.  
  151.                     /* Add another byte. */
  152.  
  153.                 BytesWritten++;
  154.             }
  155.         }
  156.     }
  157.  
  158.     return(BytesWritten);
  159. }
  160.  
  161.     /* NameToCode(STRPTR Name):
  162.      *
  163.      *    Translate a symbolic character code name of numeral.
  164.      */
  165.  
  166. UBYTE
  167. NameToCode(STRPTR Name)
  168. {
  169.     LONG i;
  170.  
  171.     for(i = 0 ; i < 44 ; i++)
  172.     {
  173.         if(!Stricmp(CodeTab[i] . Name,Name))
  174.             return(CodeTab[i] . Value);
  175.     }
  176.  
  177.     return((UBYTE)Atol(Name));
  178. }
  179.  
  180.     /* CodeToName(UBYTE Code):
  181.      *
  182.      *    Translate a character code into a symbolic
  183.      *    name or numeral.
  184.      */
  185.  
  186. STRPTR
  187. CodeToName(UBYTE Code)
  188. {
  189.     STATIC UBYTE Name[6];
  190.  
  191.     LONG i;
  192.  
  193.     for(i = 0 ; i < 44 ; i++)
  194.     {
  195.         if(CodeTab[i] . Value == Code)
  196.             return(CodeTab[i] . Name);
  197.     }
  198.  
  199.     SPrintf(Name,"%03ld",Code);
  200.  
  201.     return(Name);
  202. }
  203.  
  204.     /* FreeTranslationTable(struct TranslationEntry **Table):
  205.      *
  206.      *    Free a character translation table.
  207.      */
  208.  
  209. VOID
  210. FreeTranslationTable(struct TranslationEntry **Table)
  211. {
  212.     LONG i;
  213.  
  214.     for(i = 0 ; i < 256 ; i++)
  215.     {
  216.         if(Table[i])
  217.             FreeTranslationEntry(Table[i]);
  218.     }
  219.  
  220.     FreeVecPooled(Table);
  221. }
  222.  
  223.     /* AllocTranslationTable():
  224.      *
  225.      *    Allocate a character translation table.
  226.      */
  227.  
  228. struct TranslationEntry **
  229. AllocTranslationTable()
  230. {
  231.     return((struct TranslationEntry **)AllocVecPooled(sizeof(struct TranslationEntry *) * 256,MEMF_ANY|MEMF_CLEAR));
  232. }
  233.  
  234.     /* FreeTranslationEntry(struct TranslationEntry *Entry):
  235.      *
  236.      *    Free a character translation table entry.
  237.      */
  238.  
  239. VOID
  240. FreeTranslationEntry(struct TranslationEntry *Entry)
  241. {
  242.     FreeVecPooled(Entry);
  243. }
  244.  
  245.     /* TranslateString(STRPTR From,STRPTR To):
  246.      *
  247.      *    Translate a string to contain control codes
  248.      *    into a string to contain the real codes.
  249.      */
  250.  
  251. LONG
  252. TranslateString(STRPTR From,STRPTR To)
  253. {
  254.     BOOL    GotControl    = FALSE,
  255.         GotEscape    = FALSE;
  256.  
  257.     LONG    Len    = strlen(From),
  258.         Count    = 0,
  259.         i;
  260.  
  261.     for(i = 0 ; i < Len ; i++)
  262.     {
  263.         if(!GotControl && !GotEscape)
  264.         {
  265.             if(From[i] == '\\')
  266.             {
  267.                 GotControl = TRUE;
  268.  
  269.                 continue;
  270.             }
  271.  
  272.             if(From[i] == '^')
  273.             {
  274.                 GotEscape = TRUE;
  275.  
  276.                 continue;
  277.             }
  278.  
  279.             To[Count++] = From[i];
  280.         }
  281.         else
  282.         {
  283.             if(GotEscape)
  284.             {
  285.                 if(ToUpper(From[i]) >= 'A' && ToUpper(From[i]) <= '_')
  286.                     To[Count++] = ToUpper(From[i]) - '@';
  287.                 else
  288.                     To[Count++] = From[i];
  289.  
  290.                 GotEscape = FALSE;
  291.             }
  292.             else
  293.             {
  294.                 if(GotControl)
  295.                 {
  296.                     switch(ToUpper(From[i]))
  297.                     {
  298.                             /* These macro commands are plainly
  299.                              * ignored.
  300.                              */
  301.  
  302.                         case '0':
  303.                         case '1':
  304.                         case '2':
  305.                         case '3':
  306.                         case '4':
  307.                         case '5':
  308.                         case '6':
  309.  
  310.                             break;
  311.  
  312.                             /* These are macro commands and
  313.                              * not supported.
  314.                              */
  315.  
  316.                         case 'A':
  317.                         case 'C':
  318.                         case 'D':
  319.                         case 'G':
  320.                         case 'H':
  321.                         case 'I':
  322.                         case 'P':
  323.                         case 'U':
  324.                         case 'X':
  325.  
  326.                             To[Count++] = '\\';
  327.                             To[Count++] = From[i];
  328.                             break;
  329.  
  330.                             /* Translate code. */
  331.  
  332.                         case '*':
  333.  
  334.                             i++;
  335.  
  336.                             while(i < Len && From[i] == ' ')
  337.                                 i++;
  338.  
  339.                             if(i < Len)
  340.                             {
  341.                                 UBYTE DummyBuffer[5],j = 0,Char;
  342.  
  343.                                 if(From[i] >= '0' && From[i] <= '9')
  344.                                 {
  345.                                     while(j < 3 && i < Len)
  346.                                     {
  347.                                         Char = From[i++];
  348.  
  349.                                         if(Char >= '0' && Char <= '9')
  350.                                             DummyBuffer[j++] = Char;
  351.                                         else
  352.                                         {
  353.                                             i--;
  354.  
  355.                                             break;
  356.                                         }
  357.                                     }
  358.                                 }
  359.                                 else
  360.                                 {
  361.                                     while(j < 4 && i < Len)
  362.                                     {
  363.                                         Char = ToLower(From[i++]);
  364.  
  365.                                         if((Char >= '0' && Char <= '9') || (Char >= 'a' && Char <= 'z'))
  366.                                             DummyBuffer[j++] = Char;
  367.                                         else
  368.                                         {
  369.                                             i--;
  370.  
  371.                                             break;
  372.                                         }
  373.                                     }
  374.                                 }
  375.  
  376.                                 DummyBuffer[j] = 0;
  377.  
  378.                                 To[Count++] = NameToCode(DummyBuffer);
  379.                             }
  380.  
  381.                             i--;
  382.  
  383.                             break;
  384.  
  385.                             /* This is a backspace. */
  386.  
  387.                         case 'B':
  388.  
  389.                             To[Count++] = '\b';
  390.                             break;
  391.  
  392.                             /* This is a form feed. */
  393.  
  394.                         case 'F':
  395.  
  396.                             To[Count++] = '\f';
  397.                             break;
  398.  
  399.                             /* This is a line feed. */
  400.  
  401.                         case 'N':
  402.  
  403.                             To[Count++] = '\n';
  404.                             break;
  405.  
  406.                             /* This is a carriage return. */
  407.  
  408.                         case 'R':
  409.  
  410.                             To[Count++] = '\r';
  411.                             break;
  412.  
  413.                             /* This is a tab. */
  414.  
  415.                         case 'T':
  416.  
  417.                             To[Count++] = '\t';
  418.                             break;
  419.  
  420.                             /* Produce the escape character. */
  421.  
  422.                         case 'E':
  423.  
  424.                             To[Count++] = ESC;
  425.                             break;
  426.  
  427.                             /* Stuff the character into the buffer. */
  428.  
  429.                         default:
  430.  
  431.                             To[Count++] = From[i];
  432.                             break;
  433.                     }
  434.  
  435.                     GotControl = FALSE;
  436.                 }
  437.             }
  438.         }
  439.     }
  440.  
  441.     return(Count);
  442. }
  443.  
  444.     /* AllocTranslationEntry(STRPTR String):
  445.      *
  446.      *    Allocate a character translation table entry.
  447.      */
  448.  
  449. struct TranslationEntry *
  450. AllocTranslationEntry(STRPTR String)
  451. {
  452.     LONG Count = TranslateString(String,SharedBuffer);
  453.  
  454.     if(Count > 0)
  455.     {
  456.         struct TranslationEntry    *Entry;
  457.         UBYTE             Type;
  458.  
  459.         if(Count > 1)
  460.         {
  461.             Type = TRANSLATE_STRING;
  462.  
  463.             if(Entry = (struct TranslationEntry *)AllocVecPooled(sizeof(struct TranslationEntry) + Count + 1,MEMF_ANY|MEMF_CLEAR))
  464.             {
  465.                 Entry -> String    = (STRPTR)(Entry + 1);
  466.  
  467.                 CopyMem(SharedBuffer,Entry -> String,Count);
  468.             }
  469.         }
  470.         else
  471.         {
  472.             Type = TRANSLATE_SINGLE;
  473.  
  474.             if(Entry = (struct TranslationEntry *)AllocVecPooled(sizeof(struct TranslationEntry),MEMF_ANY|MEMF_CLEAR))
  475.             {
  476.                 Entry -> String    = &Entry -> Extra;
  477.                 Entry -> Extra    = SharedBuffer[0];
  478.             }
  479.         }
  480.  
  481.         if(Entry)
  482.         {
  483.             Entry -> Type    = Type;
  484.             Entry -> Len    = Count;
  485.  
  486.             return(Entry);
  487.         }
  488.     }
  489.  
  490.     return(NULL);
  491. }
  492.  
  493.     /* FillTranslationTable(struct TranslationEntry **Table):
  494.      *
  495.      *    Fill the translation table with defaults.
  496.      */
  497.  
  498. BOOL
  499. FillTranslationTable(struct TranslationEntry **Table)
  500. {
  501.     BOOL Success = TRUE;
  502.     LONG i;
  503.  
  504.     for(i = 0 ; Success && i < 256 ; i++)
  505.     {
  506.         if(Table[i] = (struct TranslationEntry *)AllocVecPooled(sizeof(struct TranslationEntry),MEMF_ANY|MEMF_CLEAR))
  507.         {
  508.             Table[i] -> Type    = TRANSLATE_SINGLE;
  509.             Table[i] -> String    = &Table[i] -> Extra;
  510.             Table[i] -> Extra    = i;
  511.             Table[i] -> Len        = 1;
  512.         }
  513.         else
  514.             Success = FALSE;
  515.     }
  516.  
  517.     if(!Success)
  518.     {
  519.         for(i = 0 ; i < 256 ; i++)
  520.         {
  521.             FreeVecPooled(Table[i]);
  522.             Table[i] = NULL;
  523.         }
  524.     }
  525.  
  526.     return(Success);
  527. }
  528.  
  529.     /* IsStandardTable(struct TranslationEntry **Table):
  530.      *
  531.      *    Checks a translation table to see if it contains
  532.      *    standard data.
  533.      */
  534.  
  535. BOOL
  536. IsStandardTable(struct TranslationEntry **Table)
  537. {
  538.     LONG i;
  539.  
  540.     for(i = 0 ; i < 256 ; i++)
  541.     {
  542.         if(Table[i])
  543.         {
  544.             if(Table[i] -> Type != TRANSLATE_SINGLE || Table[i] -> Len != 1 || Table[i] -> String[0] != i)
  545.                 return(FALSE);
  546.         }
  547.         else
  548.             return(FALSE);
  549.     }
  550.  
  551.     return(TRUE);
  552. }
  553.  
  554.     /* TranslateBack(STRPTR From,LONG Len,STRPTR To):
  555.      *
  556.      *    Translate a precompiled translation string
  557.      *    back.
  558.      */
  559.  
  560. VOID
  561. TranslateBack(STRPTR From,LONG Len,STRPTR To)
  562. {
  563.     STATIC char TypeTable[256] =
  564.     {
  565.          1 , 1 , 1 , 1 , 1 , 1 , 1 ,1 ,'b','t','n', 1 ,'f','r', 1 , 1,
  566.          1 , 1 , 1 , 1 , 1 , 1 , 1 ,1 , 1 , 1 , 1 ,'e', 1 , 1 , 1 , 1,
  567.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  568.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  569.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  570.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 ,'\\',2 , 2 , 2,
  571.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  572.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 0,
  573.          0 , 0 , 0 , 0 , 0 , 0 , 0 ,0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
  574.          0 , 0 , 0 , 0 , 0 , 0 , 0 ,0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
  575.          0 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 0 , 2 , 2,
  576.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  577.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  578.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  579.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  580.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2
  581.     };
  582.  
  583.     STRPTR     Buffer;
  584.     LONG    i,j,BufLen;
  585.  
  586.     for(i = j = 0 ; i < Len ; i++)
  587.     {
  588.         switch(TypeTable[From[i]])
  589.         {
  590.             case 0:    To[j++] = '\\';
  591.                 To[j++] = '*';
  592.  
  593.                 Buffer = CodeToName(From[i]);
  594.  
  595.                 BufLen = strlen(Buffer);
  596.  
  597.                 CopyMem(Buffer,&To[j],BufLen);
  598.  
  599.                 j += BufLen;
  600.  
  601.                 break;
  602.  
  603.             case 1:    To[j++] = '^';
  604.                 To[j++] = From[i] + '@';
  605.                 break;
  606.  
  607.             case 2:    To[j++] = From[i];
  608.                 break;
  609.  
  610.             default:To[j++] = '\\';
  611.                 To[j++] = TypeTable[From[i]];
  612.                 break;
  613.         }
  614.     }
  615.  
  616.     To[j] = 0;
  617. }
  618.  
  619.     /* SaveTranslationTables():
  620.      *
  621.      *    Save a character translation table to a file.
  622.      */
  623.  
  624. BOOL
  625. SaveTranslationTables(STRPTR Name,struct TranslationEntry **SendTable,struct TranslationEntry **ReceiveTable)
  626. {
  627.     BOOL    Success = FALSE,
  628.         DoIt = FALSE;
  629.     LONG    i;
  630.     LONG    Error = 0;
  631.  
  632.     for(i = 0 ; !DoIt && i < 256 ; i++)
  633.     {
  634.         if(SendTable[i] || ReceiveTable[i])
  635.             DoIt = TRUE;
  636.     }
  637.  
  638.     if(DoIt)
  639.     {
  640.         struct IFFHandle    *Handle;
  641.         UBYTE             MasterTable[256];
  642.  
  643.         for(i = 0 ; i < 256 ; i++)
  644.         {
  645.             if(SendTable[i])
  646.             {
  647.                 if(SendTable[i] -> Type == TRANSLATE_SINGLE && SendTable[i] -> Len == 1 && SendTable[i] -> String[0] == i)
  648.                     MasterTable[i] = TRANSLATION_VERBATIM;
  649.                 else
  650.                     MasterTable[i] = TRANSLATION_OTHER;
  651.             }
  652.             else
  653.                 MasterTable[i] = TRANSLATION_IGNORE;
  654.  
  655.             if(ReceiveTable[i])
  656.             {
  657.                 if(ReceiveTable[i] -> Type == TRANSLATE_SINGLE && ReceiveTable[i] -> Len == 1 && ReceiveTable[i] -> String[0] == i)
  658.                     MasterTable[i] |= TRANSLATION_VERBATIM << 4;
  659.                 else
  660.                     MasterTable[i] |= TRANSLATION_OTHER << 4;
  661.             }
  662.             else
  663.                 MasterTable[i] |= TRANSLATION_IGNORE << 4;
  664.         }
  665.  
  666.         if(Handle = AllocIFF())
  667.         {
  668.             if(Handle -> iff_Stream = Open(Name,MODE_NEWFILE))
  669.             {
  670.                 InitIFFasDOS(Handle);
  671.  
  672.                 if(!(Error = OpenIFF(Handle,IFFF_WRITE)))
  673.                 {
  674.                     if(!(Error = PushChunk(Handle,ID_TERM,ID_CAT,IFFSIZE_UNKNOWN)))
  675.                     {
  676.                         if(!(Error = PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN)))
  677.                         {
  678.                             if(!(Error = PushChunk(Handle,0,ID_VERS,IFFSIZE_UNKNOWN)))
  679.                             {
  680.                                 struct TermInfo TermInfo;
  681.  
  682.                                 TermInfo . Version    = CONFIG_FILE_VERSION;
  683.                                 TermInfo . Revision    = CONFIG_FILE_REVISION;
  684.  
  685.                                 if(WriteChunkRecords(Handle,&TermInfo,sizeof(struct TermInfo),1))
  686.                                 {
  687.                                     if(!(Error = PopChunk(Handle)))
  688.                                     {
  689.                                         if(!(Error = PushChunk(Handle,0,ID_TRNS,256)))
  690.                                         {
  691.                                             if(WriteChunkBytes(Handle,MasterTable,256) == 256)
  692.                                             {
  693.                                                 if(!(Error = PopChunk(Handle)))
  694.                                                 {
  695.                                                     if(!(Error = PopChunk(Handle)))
  696.                                                     {
  697.                                                         struct TranslationHeader Header;
  698.  
  699.                                                         Success = TRUE;
  700.  
  701.                                                         for(i = 0 ; Success && i < 256 ; i++)
  702.                                                         {
  703.                                                             if(SendTable[i] && (MasterTable[i] & 0xF) == TRANSLATION_OTHER)
  704.                                                             {
  705.                                                                 Header . Type    = SendTable[i] -> Type;
  706.                                                                 Header . Len    = SendTable[i] -> Len;
  707.                                                                 Header . Code    = i;
  708.                                                                 Header . Pad    = 0;
  709.  
  710.                                                                 if(!(Error = PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN)))
  711.                                                                 {
  712.                                                                     if(!(Error = PushChunk(Handle,0,ID_SEND,sizeof(struct TranslationHeader))))
  713.                                                                     {
  714.                                                                         if(WriteChunkRecords(Handle,&Header,sizeof(struct TranslationHeader),1))
  715.                                                                         {
  716.                                                                             if(!(Error = PopChunk(Handle)))
  717.                                                                             {
  718.                                                                                 if(!(Error = PushChunk(Handle,0,ID_CHRS,SendTable[i] -> Len)))
  719.                                                                                 {
  720.                                                                                     if(WriteChunkRecords(Handle,SendTable[i] -> String,SendTable[i] -> Len,1))
  721.                                                                                     {
  722.                                                                                         if(Error = PopChunk(Handle))
  723.                                                                                             Success = FALSE;
  724.                                                                                     }
  725.                                                                                     else
  726.                                                                                     {
  727.                                                                                         Error = IoErr();
  728.  
  729.                                                                                         Success = FALSE;
  730.                                                                                     }
  731.                                                                                 }
  732.                                                                             }
  733.                                                                             else
  734.                                                                                 Success = FALSE;
  735.                                                                         }
  736.                                                                         else
  737.                                                                         {
  738.                                                                             Error = IoErr();
  739.  
  740.                                                                             Success = FALSE;
  741.                                                                         }
  742.                                                                     }
  743.  
  744.                                                                     if(Success)
  745.                                                                     {
  746.                                                                         if(PopChunk(Handle))
  747.                                                                             Success = FALSE;
  748.                                                                     }
  749.                                                                 }
  750.                                                                 else
  751.                                                                     Success = FALSE;
  752.                                                             }
  753.  
  754.                                                             if(ReceiveTable[i] && (MasterTable[i] >> 4) == TRANSLATION_OTHER)
  755.                                                             {
  756.                                                                 Header . Type    = ReceiveTable[i] -> Type;
  757.                                                                 Header . Len    = ReceiveTable[i] -> Len;
  758.                                                                 Header . Code    = i;
  759.                                                                 Header . Pad    = 0;
  760.  
  761.                                                                 if(!(Error = PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN)))
  762.                                                                 {
  763.                                                                     if(!(Error = PushChunk(Handle,0,ID_RECV,sizeof(struct TranslationHeader))))
  764.                                                                     {
  765.                                                                         if(WriteChunkRecords(Handle,&Header,sizeof(struct TranslationHeader),1))
  766.                                                                         {
  767.                                                                             if(!(Error = PopChunk(Handle)))
  768.                                                                             {
  769.                                                                                 if(!(Error = PushChunk(Handle,0,ID_CHRS,ReceiveTable[i] -> Len)))
  770.                                                                                 {
  771.                                                                                     if(WriteChunkRecords(Handle,ReceiveTable[i] -> String,ReceiveTable[i] -> Len,1))
  772.                                                                                     {
  773.                                                                                         if(Error = PopChunk(Handle))
  774.                                                                                             Success = FALSE;
  775.                                                                                     }
  776.                                                                                     else
  777.                                                                                     {
  778.                                                                                         Error = IoErr();
  779.  
  780.                                                                                         Success = FALSE;
  781.                                                                                     }
  782.                                                                                 }
  783.                                                                             }
  784.                                                                             else
  785.                                                                                 Success = FALSE;
  786.                                                                         }
  787.                                                                         else
  788.                                                                         {
  789.                                                                             Error = IoErr();
  790.  
  791.                                                                             Success = FALSE;
  792.                                                                         }
  793.                                                                     }
  794.  
  795.                                                                     if(Success)
  796.                                                                     {
  797.                                                                         if(Error = PopChunk(Handle))
  798.                                                                             Success = FALSE;
  799.                                                                     }
  800.                                                                 }
  801.                                                                 else
  802.                                                                     Success = FALSE;
  803.                                                             }
  804.                                                         }
  805.                                                     }
  806.                                                 }
  807.                                             }
  808.                                             else
  809.                                                 Error = IoErr();
  810.                                         }
  811.                                     }
  812.                                 }
  813.                                 else
  814.                                     Error = IoErr();
  815.                             }
  816.                         }
  817.  
  818.                         if(Success)
  819.                         {
  820.                             if(PopChunk(Handle))
  821.                                 Success = FALSE;
  822.                         }
  823.                     }
  824.  
  825.                     CloseIFF(Handle);
  826.                 }
  827.  
  828.                 Close(Handle -> iff_Stream);
  829.  
  830.                 if(Success)
  831.                     AddProtection(Name,FIBF_EXECUTE);
  832.                 else
  833.                     DeleteFile(Name);
  834.             }
  835.             else
  836.                 Error = IoErr();
  837.  
  838.             FreeIFF(Handle);
  839.         }
  840.         else
  841.             Error = ERR_NO_MEM;
  842.     }
  843.  
  844.     if(Error)
  845.         SetIoErr(Error);
  846.  
  847.     return(Success);
  848. }
  849.  
  850.     /* LoadTranslationTable()s:
  851.      *
  852.      *    Load a translation table from a file.
  853.      */
  854.  
  855. BOOL
  856. LoadTranslationTables(STRPTR Name,struct TranslationEntry **SendTable,struct TranslationEntry **ReceiveTable)
  857. {
  858.     STATIC ULONG Stops[5 * 2] =
  859.     {
  860.         ID_TERM,    ID_VERS,
  861.         ID_TERM,    ID_TRNS,
  862.         ID_TERM,    ID_SEND,
  863.         ID_TERM,    ID_RECV,
  864.         ID_TERM,    ID_CHRS
  865.     };
  866.  
  867.     struct IFFHandle    *Handle;
  868.     BOOL             Success = FALSE;
  869.     LONG             i;
  870.  
  871.     UBYTE             MasterTable[256];
  872.     BOOL             GotMasterTable = FALSE;
  873.     LONG             Error;
  874.  
  875.     if(Handle = AllocIFF())
  876.     {
  877.         if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
  878.         {
  879.             InitIFFasDOS(Handle);
  880.  
  881.             if(!(Error = OpenIFF(Handle,IFFF_READ)))
  882.             {
  883.                 if(!(Error = StopChunks(Handle,(LONG *)Stops,5)))
  884.                 {
  885.                     struct ContextNode        *Chunk;
  886.                     struct TermInfo             TermInfo;
  887.                     struct TranslationHeader     Header;
  888.                     LONG                 LastType = TYPE_NONE;
  889.  
  890.                     Success = TRUE;
  891.  
  892.                     while(Success && !ParseIFF(Handle,IFFPARSE_SCAN))
  893.                     {
  894.                         Chunk = CurrentChunk(Handle);
  895.  
  896.                         switch(Chunk -> cn_ID)
  897.                         {
  898.                             case ID_VERS:
  899.  
  900.                                 if(ReadChunkBytes(Handle,&TermInfo,sizeof(struct TermInfo)) == sizeof(struct TermInfo))
  901.                                 {
  902.                                     if(TermInfo . Version > CONFIG_FILE_VERSION || (TermInfo . Version == CONFIG_FILE_VERSION && TermInfo . Revision > CONFIG_FILE_REVISION))
  903.                                     {
  904.                                         Error = ERR_OUTDATED;
  905.  
  906.                                         Success = FALSE;
  907.                                     }
  908.                                 }
  909.                                 else
  910.                                 {
  911.                                     Error = IoErr();
  912.  
  913.                                     Success = FALSE;
  914.                                 }
  915.  
  916.                                 break;
  917.  
  918.                             case ID_TRNS:
  919.  
  920.                                 if(ReadChunkBytes(Handle,MasterTable,256) == 256)
  921.                                     GotMasterTable = TRUE;
  922.                                 else
  923.                                 {
  924.                                     Error = IoErr();
  925.  
  926.                                     Success = FALSE;
  927.                                 }
  928.  
  929.                                 break;
  930.  
  931.                             case ID_SEND:
  932.  
  933.                                 if(LastType != TYPE_NONE)
  934.                                     Success = FALSE;
  935.                                 else
  936.                                 {
  937.                                     if(!ReadChunkRecords(Handle,&Header,MIN(sizeof(struct TranslationHeader),Chunk -> cn_Size),1))
  938.                                     {
  939.                                         Error = IoErr();
  940.  
  941.                                         Success = FALSE;
  942.                                     }
  943.                                     else
  944.                                         LastType = TYPE_SEND;
  945.                                 }
  946.  
  947.                                 break;
  948.  
  949.                             case ID_RECV:
  950.  
  951.                                 if(LastType != TYPE_NONE)
  952.                                 {
  953.                                     Error = IFFERR_MANGLED;
  954.  
  955.                                     Success = FALSE;
  956.                                 }
  957.                                 else
  958.                                 {
  959.                                     if(!ReadChunkRecords(Handle,&Header,MIN(sizeof(struct TranslationHeader),Chunk -> cn_Size),1))
  960.                                     {
  961.                                         Success = FALSE;
  962.  
  963.                                         Error = IoErr();
  964.                                     }
  965.                                     else
  966.                                         LastType = TYPE_RECEIVE;
  967.                                 }
  968.  
  969.                                 break;
  970.  
  971.                             case ID_CHRS:
  972.  
  973.                                 if(LastType == TYPE_NONE)
  974.                                 {
  975.                                     Error = IFFERR_MANGLED;
  976.  
  977.                                     Success = FALSE;
  978.                                 }
  979.                                 else
  980.                                 {
  981.                                     if(ReadChunkRecords(Handle,SharedBuffer,Header . Len,1))
  982.                                     {
  983.                                         struct TranslationEntry *Entry;
  984.  
  985.                                         if(Header . Type == TRANSLATE_SINGLE)
  986.                                         {
  987.                                             if(Entry = (struct TranslationEntry *)AllocVecPooled(sizeof(struct TranslationEntry),MEMF_ANY|MEMF_CLEAR))
  988.                                             {
  989.                                                 Entry -> String    = &Entry -> Extra;
  990.                                                 Entry -> Extra    = SharedBuffer[0];
  991.                                             }
  992.                                         }
  993.                                         else
  994.                                         {
  995.                                             if(Entry = (struct TranslationEntry *)AllocVecPooled(sizeof(struct TranslationEntry) + Header . Len + 1,MEMF_ANY|MEMF_CLEAR))
  996.                                             {
  997.                                                 Entry -> String    = (STRPTR)(Entry + 1);
  998.  
  999.                                                 CopyMem(SharedBuffer,Entry -> String,Header . Len);
  1000.                                             }
  1001.                                         }
  1002.  
  1003.                                         if(Entry)
  1004.                                         {
  1005.                                             Entry -> Type    = Header . Type;
  1006.                                             Entry -> Len    = Header . Len;
  1007.  
  1008.                                             if(LastType == TYPE_SEND)
  1009.                                                 SendTable[Header . Code]    = Entry;
  1010.                                             else
  1011.                                                 ReceiveTable[Header . Code]    = Entry;
  1012.  
  1013.                                             LastType = TYPE_NONE;
  1014.                                         }
  1015.                                         else
  1016.                                         {
  1017.                                             Error = ERR_NO_MEM;
  1018.  
  1019.                                             Success = FALSE;
  1020.                                         }
  1021.                                     }
  1022.                                     else
  1023.                                     {
  1024.                                         Error = IoErr();
  1025.  
  1026.                                         Success = FALSE;
  1027.                                     }
  1028.                                 }
  1029.  
  1030.                                 break;
  1031.                         }
  1032.                     }
  1033.                 }
  1034.  
  1035.                 CloseIFF(Handle);
  1036.             }
  1037.  
  1038.             Close(Handle -> iff_Stream);
  1039.         }
  1040.         else
  1041.             Error = IoErr();
  1042.  
  1043.         FreeIFF(Handle);
  1044.     }
  1045.     else
  1046.         Error = ERR_NO_MEM;
  1047.  
  1048.     if(Success && GotMasterTable)
  1049.     {
  1050.         struct TranslationEntry *Entry;
  1051.  
  1052.         for(i = 0 ; i < 256 ; i++)
  1053.         {
  1054.             if((MasterTable[i] & 0xF) == TRANSLATION_VERBATIM)
  1055.             {
  1056.                 if(Entry = (struct TranslationEntry *)AllocVecPooled(sizeof(struct TranslationEntry),MEMF_ANY|MEMF_CLEAR))
  1057.                 {
  1058.                     Entry -> Type    = TRANSLATE_SINGLE;
  1059.                     Entry -> String    = &Entry -> Extra;
  1060.                     Entry -> Extra    = i;
  1061.                     Entry -> Len    = 1;
  1062.  
  1063.                     SendTable[i] = Entry;
  1064.                 }
  1065.                 else
  1066.                 {
  1067.                     Error = ERR_NO_MEM;
  1068.  
  1069.                     Success = FALSE;
  1070.  
  1071.                     break;
  1072.                 }
  1073.             }
  1074.  
  1075.             if((MasterTable[i] >> 4) == TRANSLATION_VERBATIM)
  1076.             {
  1077.                 if(Entry = (struct TranslationEntry *)AllocVecPooled(sizeof(struct TranslationEntry),MEMF_ANY|MEMF_CLEAR))
  1078.                 {
  1079.                     Entry -> Type    = TRANSLATE_SINGLE;
  1080.                     Entry -> String    = &Entry -> Extra;
  1081.                     Entry -> Extra    = i;
  1082.                     Entry -> Len    = 1;
  1083.  
  1084.                     ReceiveTable[i] = Entry;
  1085.                 }
  1086.                 else
  1087.                 {
  1088.                     Error = ERR_NO_MEM;
  1089.  
  1090.                     Success = FALSE;
  1091.  
  1092.                     break;
  1093.                 }
  1094.             }
  1095.         }
  1096.     }
  1097.  
  1098.     if(!Success)
  1099.     {
  1100.         for(i = 0 ; i < 256 ; i++)
  1101.         {
  1102.             if(SendTable[i])
  1103.             {
  1104.                 FreeTranslationEntry(SendTable[i]);
  1105.  
  1106.                 SendTable[i] = NULL;
  1107.             }
  1108.  
  1109.             if(ReceiveTable[i])
  1110.             {
  1111.                 FreeTranslationEntry(ReceiveTable[i]);
  1112.  
  1113.                 ReceiveTable[i] = NULL;
  1114.             }
  1115.         }
  1116.     }
  1117.  
  1118.     if(Error)
  1119.         SetIoErr(Error);
  1120.  
  1121.     return(Success);
  1122. }
  1123.